﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.Web.Script.Serialization;

namespace Skyworth.CRM.Common
{
    /// <summary>
    /// Serialie objct and Deserialize objct
    /// </summary>
    public static class SerializationHelper
    {
        // Store the type of object which being used frequently
        private static Dictionary<int, XmlSerializer> serializerDictionary = new Dictionary<int, XmlSerializer>();

        /// <summary>
        /// Get serializer by type
        /// </summary>
        /// <param name="parameter">the type of object</param>
        /// <returns>a XmlSerializer</returns>
        /// Change History
        /// Date                Changer             Description
        /// ---                 ---                 ---
        public static XmlSerializer GetSerializer(Type type)
        {
            int typeHashCode = type.GetHashCode();

            if (!serializerDictionary.ContainsKey(typeHashCode))
                serializerDictionary.Add(typeHashCode, new XmlSerializer(type));

            return serializerDictionary[typeHashCode];
        }

        #region Serialize and deserialize between string and object
        /// <summary>
        /// Get a string which is serialized with a object
        /// </summary>
        /// <param name="obj">the object which want to be serialized</param>
        /// <returns>a string</returns>
        /// Change History
        /// Date                Changer             Description
        /// ---                 ---                 ---
        public static string Serialize(object obj)
        {
            string returnStr = "";
            XmlSerializer serializer = GetSerializer(obj.GetType());
            MemoryStream memoryStream = new MemoryStream();
            XmlTextWriter xmlTextWriter = null;
            StreamReader streamReader = null;

            try
            {
                xmlTextWriter = new System.Xml.XmlTextWriter(memoryStream, Encoding.UTF8);
                xmlTextWriter.Formatting = System.Xml.Formatting.Indented;
                serializer.Serialize(xmlTextWriter, obj);
                memoryStream.Seek(0, SeekOrigin.Begin);
                streamReader = new StreamReader(memoryStream);
                returnStr = streamReader.ReadToEnd();
            }
            finally
            {
                if (xmlTextWriter != null)
                    xmlTextWriter.Close();
                if (streamReader != null)
                    streamReader.Close();
                memoryStream.Close();
            }

            return returnStr;
        }

        /// <summary>
        /// Deserialize a object from a serialized string
        /// </summary>
        /// <typeparam name="T">the type of the object</typeparam>
        /// <param name="serializedString">the serialized string</param>
        /// <returns>an object</returns>
        /// Change History
        /// Date                Changer             Description
        /// ---                 ---                 ---
        public static T Deserialize<T>(string serializedString)
        {
            byte[] bytes = Encoding.UTF8.GetBytes(serializedString);
            XmlSerializer serializer = GetSerializer(typeof(T));
            if (serializer != null)
            {
                return (T)serializer.Deserialize(new MemoryStream(bytes));
            }
            else
            {
                return default(T);
            }
        }
        #endregion

        #region Serialize and deserialize between a xml file and object
        /// <summary>
        /// Serialize an object to a xml file
        /// </summary>
        /// <param name="obj">the object which want to be serialized</param>
        /// <param name="filename">the path of the file</param>
        /// <returns>is it successful</returns>
        public static bool SerializeToFile(object obj, string filename)
        {
            bool isSuccess = false;

            if (obj != null && File.Exists(filename))
            {
                FileStream fileStream = null;

                try
                {
                    fileStream = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
                    XmlSerializer serializer = GetSerializer(obj.GetType());
                    serializer.Serialize(fileStream, obj);
                    isSuccess = true;
                }
                finally
                {
                    if (fileStream != null)
                        fileStream.Close();
                }
            }

            return isSuccess;
        }

        /// <summary>
        /// Deserialize an object from a xml file
        /// </summary>
        /// <typeparam name="T">the type of the object</typeparam>
        /// <param name="filename">the path of the file</param>
        /// <returns>an object</returns>
        public static T DeserializeFromFile<T>(string filename)
        {
            FileStream fileStream = null;
            try
            {
                fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                XmlSerializer serializer = GetSerializer(typeof(T));
                if (serializer != null)
                {
                    return (T)serializer.Deserialize(fileStream);
                }
                else
                {
                    return default(T);
                }
            }
            finally
            {
                if (fileStream != null)
                    fileStream.Close();
            }
        }
        #endregion

        #region deserialize between json and object
        //Henry added it on 20110110
        public static T DeserializeJson<T>(string json)
        {
            JavaScriptSerializer jss = new JavaScriptSerializer();
            T obj = jss.Deserialize<T>(json);
            return obj;
        }
        #endregion

        public static string DataTable2Json(DataTable dtb)
        {
            JavaScriptSerializer jss = new JavaScriptSerializer();
            ArrayList dic = new ArrayList();
            foreach (DataRow row in dtb.Rows)
            {
                Dictionary<string, object> drow = new Dictionary<string, object>();
                foreach (DataColumn col in dtb.Columns)
                {
                    drow.Add(col.ColumnName, row[col.ColumnName]);
                }
                dic.Add(drow);
            }
            return jss.Serialize(dic);
        }

        public static DataTable Json2DataTable(string json)
        {
            JavaScriptSerializer jss = new JavaScriptSerializer();
            ArrayList dic = jss.Deserialize<ArrayList>(json);
            DataTable dtb = new DataTable();
            if (dic.Count > 0)
            {
                foreach (Dictionary<string, object> drow in dic)
                {
                    if (dtb.Columns.Count == 0)
                    {
                        foreach (string key in drow.Keys)
                        {
                            dtb.Columns.Add(key, drow[key].GetType());
                        }
                    }
                    DataRow row = dtb.NewRow();
                    foreach (string key in drow.Keys)
                    {
                        row[key] = drow[key];
                    }
                    dtb.Rows.Add(row);
                }
            }
            return dtb;
        } 
    }
}
